package com.zzw.spring.component;

import com.zzw.spring.annotation.Component;
import com.zzw.spring.processor.BeanPostProcessor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//1.这是我们自己的一个后置处理器
//2.实现了BeanPostProcessor接口
//3.我们可以重写before和after方法
//4.在Spring容器中，仍然把ZzwBeanPostProcessor当作一个Bean对象，要注入到容器中
//5.所以用一个@Component标识把ZzwBeanPostProcessor注入到ioc容器里面
//6.我们要让ZzwBeanPostProcessor成为给真正的一个后置处理器，需要在容器中加入业务代码/支撑代码
//7.还要考虑多个后置处理器对象注入到容器的问题
//
@Component
public class ZzwBeanPostProcessor implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        //这里后置处理器是针对容器创建的所有Bean生效的
        //相当于是可以对多个对象进行编程，也就是切面编程的概念
        //日志，权限，身份，事务
        if (bean instanceof Car){
            System.out.println("发现这个是一个Car对象");
        }
        System.out.println("后置处理器ZzwBeanPostProcessor的Before被调用 bean类型是" + bean.getClass()
        + "bean的名字是" + beanName);
        return bean;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("后置处理器ZzwBeanPostProcessor的After被调用 bean类型是" + bean.getClass()
                + "bean的名字是" + beanName);

        //实现AOP，返回代理对象，即对Bean进行包装，根据实际情况进行包装
        //1.先死后活->后面我们可以通过注解就更加灵活了
        if ("smartDog".equals(beanName)){
            //使用JDK的动态代理返回该Bean的代理对象
            //这里关于动态代理的机制可以回顾一下

            Object proxyInstance = Proxy.newProxyInstance(ZzwBeanPostProcessor.class.getClassLoader(),
                    bean.getClass().getInterfaces(), new InvocationHandler() {
                        @Override
                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                            System.out.println("method=" + method.getName());
                            Object result = null;
                            //假如我们要进行前置通知+返回处理的方法是getSum
                            //后面可以通过注解来做的更加灵活Before After
                            if ("getSum".equals(method.getName())){
                                SmartAnimalAspect.showBeginLog();
                                result = method.invoke(bean,args);//执行目标方法
                                //进行返回通知的处理
                                SmartAnimalAspect.showSuccessLog();
                            }else{
                                result = method.invoke(bean,args);//执行目标方法
                            }

                            return result;

                        }
                    });
            //如果bean是需要返回代理对象的,这里就直接return代理对象
            return proxyInstance;
        }
        //如果不需要AOP，就返回原生对象，返回Bean
        return bean;
    }


}
